import datetime
import functools
import typing

from coin.base.datetime_util import iterate_date
from coin.exchange.base.strategy_logger import parse_file_name
from coin.support.proto_log.logic.util import (StratInfo,
                                               enumerate_strat_log_into_stratinfos)
from coin.tool.strat_monitor.util.monitor_util import (
    get_topic_from_strat)
from coin.util.queue.config import KafkaConfig
from coin.util.queue.tools.kafka_topic import parse_kafka_topic


def enumerate_strat_infos(
      root_dir: str,
      start_date: datetime.date,
      end_date: datetime.date,
      enumerate_func: typing.Callable[[str, str], typing.List[StratInfo]]):
  end_date += datetime.timedelta(days=1)
  trading_dates = [td for td in iterate_date(start_date, end_date)]
  strat_info_set = set()
  strat_info_list = []
  for td in trading_dates:
    td_str = td.strftime('%Y%m%d')
    strat_infos = enumerate_func(root_dir, td_str)
    for strat_info in strat_infos:
      key = (strat_info.machine, strat_info.strategy_name)
      if key not in strat_info_set:
        strat_info_set.add(key)
        strat_info_list.append(strat_info)
  return strat_info_list


def get_strat_info_list(*,
                        start_date: datetime.date,
                        end_date: datetime.date,
                        strategy_list: typing.List[str],
                        machine_list: typing.Optional[typing.List[str]]=None,
                        strat_log_root_dir: typing.Optional[str]=None,
                        kafka_config: typing.Optional[KafkaConfig]=None
) -> typing.List[StratInfo]:
  strat_infos = []
  if kafka_config is not None:
    kafka_topics = get_topic_from_strat(strategy_list, kafka_config)
    for topic in kafka_topics:
      _, strat_info = parse_kafka_topic(topic)
      strat_infos.append(strat_info)
  else:
    assert strat_log_root_dir is not None
    func = functools.partial(
        enumerate_strat_log_into_stratinfos,
        parse_f=parse_file_name)
    strat_infos = enumerate_strat_infos(strat_log_root_dir, start_date, end_date, func)
    strat_infos = [
        strat_info for strat_info in strat_infos
        if strat_info.strategy_name in set(strategy_list)
    ]
  if machine_list:
    strat_infos = [
        strat_info for strat_info in strat_infos if strat_info.machine in machine_list]
  return strat_infos
